home *** CD-ROM | disk | FTP | other *** search
- /* Controller.m -- Controller object for MailHelper application.
- Copyright 1991, Izumi Ohzawa and Manuel Alberto Ricart, All rights reserved.
- 3-17-91 V1.0 (IO)
- * Starting project.
- * Some codes are borrowed from AtYourService NeXT demo application.
- 4-6-91 V1.0 (IO)
- * Bug fix: fclose(fpin); was missing in method insertSignature.
- 9-18-91 V1.1 (MAR)
- * Preferences panel and use of default database to store them.
- Joint venture with Izumi? Perhaps. Izumi sent me his code
- for MailHelper. I told him I implement some basic prefs for him.
- 9-22-91 V1.1 (IO)
- * Defaults now written out as soon as OK button in Pref panel is pressed.
- * Signature insertion now adds a separator '---' within the code to
- remove requirement of having it in signature file itself (to make MailHelper
- conform with other programs which use .signature).
- * RTF signature insertion added.
-
- 10-9-91 V1.2 (Mitsuhiro Kishimoto)
- * Japanese re-format routine: needed to handle mixed ASCII and 2-byte EUC code.
- Original "Kin-soku" (forbidden line break) code was written
- by Masatoshi Kurihara.
-
- 9-10-93 V1.3 Mike O'Neill (emo@mitre.org) added .rtfd support, grayed rtf selection, and 3.0 colorized icon and compiled FAT
-
- To implement:
- User selectable command keys for various functions.
- */
-
-
- #import "Controller.h"
- #import <appkit/appkit.h>
-
-
- @implementation Controller
-
- /* Modified Izumi's code to load the defaults at startup.
- * It also sets up the default values on the prefs panel.
- */
- - appDidInit:sender
- {
- static NXDefaultsVector MailHelperDefaults = {
- {WIDTH,"62"},
- {QUOTE,"> "},
- {SIGFILE,SIGFILENAME},
- {RTFSIGFILE,RTFSIGFILENAME},
- {RTFDSIGFILE,RTFDSIGFILENAME},
- {NULL}
- };
- myListener = [NXApp appListener];
- [myListener setServicesDelegate: self];
-
- NXRegisterDefaults(APPNAME, MailHelperDefaults);
- wrapWidth = atoi(NXGetDefaultValue(APPNAME, WIDTH));
- [gWrapWidth setIntValue:wrapWidth];
- [gWrapScroller setIntValue:wrapWidth];
- quoteString =(char *) NXGetDefaultValue(APPNAME, QUOTE);
- [gQuoteString setStringValue:quoteString];
- sigFile =(char *) NXGetDefaultValue(APPNAME, SIGFILE);
- [gSigFileName setStringValue:sigFile];
- rtfSigFile =(char *) NXGetDefaultValue(APPNAME, RTFSIGFILE);
- [gRtfSigFileName setStringValue:rtfSigFile];
- rtfdSigFile =(char *) NXGetDefaultValue(APPNAME, RTFDSIGFILE);
- [gRtfdSigFileName setStringValue:rtfdSigFile];
- // [gRtfdText setGraphicsImportEnabled:YES];
- return self;
- }
-
-
-
- /* Brings up the Info panel. Not done on startup because it's in a separate
- * interface file. Saves startup time for the user if we do this when they ask
- * for it, and not before.
- * "infoPanel" and "helpPanel" are defined in "Info.nib".
- */
- - infoPanel:sender
- {
- if( ! infoPanel ){
- [NXApp loadNibSection:"Info.nib" owner:self];
- }
- [infoPanel makeKeyAndOrderFront:sender];
- return self;
- }
-
- // Records the prefsPanel values into the global variables
- /* [izumi] Moved from delegate method -appWillTerminate:, because it is
- * not apparently called if user is logging out from Workspace --
- * this is how MailHelper gets terminated (MailHelper is almost never
- * exited via Quit from menu.).
- */
- - prefsOK:sender
- {
- char buf[20];
- wrapWidth = (int)[gWrapWidth intValue];
- quoteString = (char *)[gQuoteString stringValue];
- sigFile = (char *)[gSigFileName stringValue];
- rtfSigFile = (char *)[gRtfSigFileName stringValue];
-
- sprintf(buf, "%d", wrapWidth);
- NXWriteDefault(APPNAME, WIDTH, buf);
- NXWriteDefault(APPNAME, QUOTE, quoteString);
- NXWriteDefault(APPNAME, SIGFILE, sigFile);
- NXWriteDefault(APPNAME, RTFSIGFILE, rtfSigFile);
- return self;
- }
-
- - prefsCancel:sender
- {
- [gWrapWidth setIntValue:wrapWidth];
- [gWrapWidth display];
- [gWrapScroller setIntValue:wrapWidth];
- [gWrapScroller display];
- [gQuoteString setStringValue:quoteString];
- [gQuoteString display];
- [gSigFileName setStringValue:sigFile];
- [gSigFileName display];
- [gRtfSigFileName setStringValue:rtfSigFile];
- [gRtfSigFileName display];
-
- return self;
- }
- /*
- * Brings up the Help panel (as above)
- */
- - helpPanel:sender
- {
- if( ! helpPanel ){
- [NXApp loadNibSection:"Info.nib" owner:self];
- }
- [helpPanel makeKeyAndOrderFront:sender];
- return self;
-
- }
-
-
-
- /* Reformats selected text so that it fits into a specified column width.
- * Alberto's Modifications:
- * initialized colLimit to wrapWidth global variable.
- */
-
- - reformatSelection:(id)pbid userData:(const char *)udata error:(char **)errmsg
- {
- char *data;
- int length;
- const char *const *types;
- int hasAscii, i;
-
- types = [pbid types]; /* get a list of pasteboard types */
- hasAscii = 0;
- for(i=0; !hasAscii && types[i]; i++)
- if(!strcmp(types[i], NXAsciiPboardType)) hasAscii = 1;
- if(hasAscii)
- {
- [pbid readType:NXAsciiPboardType data:&data length:&length];
- if(data && length)
- {
- char *returnData, *dataptr, *endptr;
- char *retptr;
- int col;
- unsigned char c1, c2;
-
- col = 0;
- returnData=malloc(length+10);
- dataptr = data;
- endptr = dataptr+length;
- retptr = returnData;
-
- while (dataptr < endptr) {
- c1 = *dataptr++;
- c2 = (iskanji (c1) ? *dataptr++ : *dataptr);
-
- switch (c1) {
- case '\n':
- if ( c2 == '\n')
- col = 0;
- else if (iskanji (c2))
- goto skip_char;
- else
- c1 = ' ';
- break;
- case '\t':
- col = (col + 8) &~ 7;
- break;
- case '\b':
- col = col ? col - 1 : 0;
- break;
- default:
- col = col + (iskanji (c1) ? 2 : 1);
- }
- if (col > wrapWidth) {
- if ( ! iskanji (c1)) {
- for (i = 1; 0 < col - i; i++) {
- c2 = *(retptr - i);
- if ( iskanji (c2) ) {
- dataptr -= i;
- retptr -= (i - 1);
- *retptr++ = '\n';
- col = 0;
- goto skip_char;
- } else if ( isspace (c2) ) {
- dataptr -= i;
- retptr -= i;
- *retptr++ = '\n';
- col = 0;
- goto skip_char;
- }
- }
- *retptr++ = '\n';
- col = 1;
- } else if (iskanji (c1) && ! KINSOKU (c1, c2)) {
- *retptr++ = '\n';
- col = 2;
- }
- }
- *retptr++= c1;
- if (iskanji (c1))
- *retptr++= c2;
- else if (c1 == '\n' && c2 == '\n') {
- *retptr++= c2;
- dataptr++;
- }
- skip_char:
- ;
- }
- *retptr++= '\n';
- *retptr = '\0';
- [pbid declareTypes:&NXAsciiPboardType num:1 owner:self];
- [pbid writeType:NXAsciiPboardType data:returnData length:strlen(returnData)];
- free(returnData);
- } /* end if(data && length) */
- else
- *errmsg = "Selection is empty.";
- } /* end if(hasAscii) */
- else
- *errmsg = "No ASCII text found in your selection.";
- return self;
- }
-
-
-
- /* Adds quotation marks "> " to the head of each line of selected text.
- * Alberto's Modification:
- * Only changed the definition of quotestr to point to the quoteString global.
- */
-
- - quoteSelection:(id)pbid userData:(const char *)udata error:(char **)errmsg
- {
- char *data;
- int length;
- const char *const *types;
- char *quotestr = quoteString;
- int hasAscii, i, quotelen;
-
- quotelen = strlen(quotestr);
- types = [pbid types]; /* get a list of pasteboard types */
- hasAscii = 0;
- for(i=0; !hasAscii && types[i]; i++)
- if(!strcmp(types[i], NXAsciiPboardType)) hasAscii = 1;
- if(hasAscii)
- {
- [pbid readType:NXAsciiPboardType data:&data length:&length];
- if(data && length)
- {
- int numlines;
- char ch;
- char *returnData, *dataptr, *endptr, *outptr;
-
- numlines = 1;
- dataptr = data; /* ptr to original data */
- endptr = data+length; /* ptr to end of data */
- while(dataptr < endptr) /* count the number of lines */
- if(*dataptr++ == '\n')
- numlines++;
- returnData=malloc(length+numlines*quotelen+10);
- dataptr = data; /* reinitialize ptr to orig data */
- outptr = returnData;
- for(i=0;i<quotelen;i++)
- *outptr++ = quotestr[i];
- while(dataptr < endptr)
- {
- if((ch = *dataptr++) == '\n')
- {
- *outptr++ = ch;
- for(i=0;i<quotelen;i++)
- *outptr++ = quotestr[i];
- }
- else
- *outptr++ = ch;
- }
- *outptr = '\n';
- *(outptr+1) = '\0';
- [pbid declareTypes:&NXAsciiPboardType num:1 owner:self];
- [pbid writeType:NXAsciiPboardType data:returnData length:strlen(returnData)];
- free(returnData);
- } /* end if(data && length) */
- else
- *errmsg = "Selection is empty.";
- } /* end if(hasAscii) */
- else
- *errmsg = "No ASCII text found in your selection.";
- return self;
- }
-
-
- // Adds the content of ~/.signature at the current cursor location.
-
- - insertSignature:(id)pbid userData:(const char *)udata error:(char **)errmsg
- {
- char *data, *dataptr;
- char *signaturefile = sigFile;
- char signaturepath[256];
- int length, i;
- struct stat filestat;
- FILE *fpin;
- sprintf(signaturepath, "%s/%s", NXHomeDirectory(), signaturefile);
- if(stat(signaturepath, &filestat))
- {
- data = "";
- length = 0;
- *errmsg = "No signature file found in your home directory.";
- }
- else
- {
- length = filestat.st_size;
- if((fpin = fopen(signaturepath, "r")) != NULL)
- {
- dataptr = data = malloc(length+NUMSIGDASH+10); /* data remains unchanged */
- for(i=0; i<NUMSIGDASH; i++) /* Add '---' signature separator here */
- *dataptr++ = '-';
- *dataptr++ = '\n';
- fread((void *)dataptr, 1, length, fpin);
- fclose(fpin); /* This was missing in V1.0 release */
- *(dataptr+length) = '\0';
- [pbid declareTypes:&NXAsciiPboardType num:1 owner:self];
- [pbid writeType:NXAsciiPboardType data:data length:strlen(data)];
- free(data);
- }
- else
- *errmsg = "Cannot open signature file.";
- }
- return self;
- }
-
- // Adds the content of ~/.signature.rtf at the current cursor location.
- // RTF signature insertion method.
- - insertRtfSignature:(id)pbid userData:(const char *)udata error:(char **)errmsg
- {
- char *data;
- char *signaturefile = rtfSigFile;
- char signaturepath[256];
- int length;
- struct stat filestat;
- FILE *fpin;
- sprintf(signaturepath, "%s/%s", NXHomeDirectory(), signaturefile);
- if(stat(signaturepath, &filestat))
- {
- data = "";
- length = 0;
- *errmsg = "No RTF signature file found in your home directory.";
- }
- else
- {
- length = filestat.st_size;
- if((fpin = fopen(signaturepath, "r")) != NULL)
- {
- data = malloc(length+10);
- fread((void *)data, 1, length, fpin);
- fclose(fpin);
- *(data+length) = '\0';
- [pbid declareTypes:&NXRTFPboardType num:1 owner:self];
- [pbid writeType:NXRTFPboardType data:data length:strlen(data)];
- free(data);
- }
- else
- *errmsg = "Cannot open RTF signature file.";
- }
- return self;
- }
-
-
- // Adds the content of ~/.signature.rtfd at the current cursor location.
- // RTFD signature insertion method.
- - insertRtfdSignature:(id)pbid userData:(const char *)udata error:(char **)errmsg
- {
- char *data;
- char *signaturefile = rtfdSigFile;
- char signaturepath[256];
- int length;
- struct stat filestat;
- sprintf(signaturepath, "%s/%s", NXHomeDirectory(), signaturefile);
- if(stat(signaturepath, &filestat))
- {
- data = "";
- length = 0;
- *errmsg = "No RTFD signature found in your home directory.";
- }
- else
- {
-
- if(![gRtfdText openRTFDFrom:signaturepath])
- {
- [tempText selectAll:self]; // This bit of code is necessary because
- [tempText paste:self]; // while Edit, Mail and Text all support RTFD
- [gRtfdText selectAll:self]; // there is as yet no proper NXAtom for the
- [gRtfdText copy:self]; // pasteboard type. So I use the copy and
- [gRtfdText writeSelectionToPasteboard:pbid types:(NXAtom *)[[Pasteboard newName:NXGeneralPboard] types]];
- [tempText selectAll:self]; // to put the text on the general pboard,
- [tempText copy:self]; //from whence I then get the types!
- }
- else
- *errmsg = "Cannot open RTFD signature.";
- }
- return self;
- }
-
- // quote an RTF selection by graying it out
- - grayRTFSelection:(id)pbid userData:(const char *)udata error:(char **)errmsg
- {
- NXAtom pbtype[] = {NXRTFPboardType, 0};
- [tempText selectAll:self];
- [tempText readSelectionFromPasteboard:pbid];
- [tempText setSelGray:NX_DKGRAY];
- [tempText writeSelectionToPasteboard:pbid types:pbtype];
- return self;
- }
-
-
- @end
-